﻿Imports QueueManager.Helper.CRM

Public Class QueryExpressionHelper
    Private _linkEntities As LinkEntityHelperCollection
    Private _criteria As FilterExpressionHelper
    Private _orders As OrderExpressionCollection
    Private _columns As ColumnSetHelper

    Private _query As QueryExpression

    ''' <summary>
    ''' Specifies the entity that will be queried
    ''' </summary>
    Public Property EntityName() As String
        Get
            Return _query.EntityName
        End Get
        Set(ByVal value As String)
            _query.EntityName = value
        End Set
    End Property

    ''' <summary>
    ''' Specifies the paging information of how to return the query
    ''' </summary>
    Public Property PageInfo() As PagingInfo
        Get
            ' since the PagingInfo may not be used, auto-instantiation occurs in the "get" property
            If _query.PageInfo Is Nothing Then
                _query.PageInfo = New PagingInfo()
            End If

            Return _query.PageInfo
        End Get
        Set(ByVal value As PagingInfo)
            _query.PageInfo = value
        End Set
    End Property

    ''' <summary>
    ''' A collection of linked entities that are used to connect the main entity with other entities
    ''' for more complex queries
    ''' </summary>
    Public ReadOnly Property LinkEntities() As LinkEntityHelperCollection
        Get
            Return _linkEntities
        End Get
    End Property

    ''' <summary>
    ''' A filter that contains a collection of conditions (and optionally, nested filters) that will be applied to the query
    ''' </summary>
    Public Property Criteria() As FilterExpressionHelper
        Get
            Return _criteria
        End Get
        Set(ByVal value As FilterExpressionHelper)
            _criteria = value
        End Set
    End Property

    ''' <summary>
    ''' Specifies the order/organization of the query
    ''' </summary>
    Public ReadOnly Property Orders() As OrderExpressionCollection
        Get
            Return _orders
        End Get
    End Property

    ''' <summary>
    ''' Specifies which columns/attributes will be returned by the query
    ''' </summary>
    Public ReadOnly Property Columns() As ColumnSetHelper
        Get
            Return _columns
        End Get
    End Property

    ''' <summary>
    ''' 
    ''' </summary>
    Public Property Distinct() As Boolean
        Get
            Return _query.Distinct
        End Get
        Set(ByVal value As Boolean)
            _query.Distinct = value
        End Set
    End Property

    ''' <summary>
    ''' Returns a QueryExpression object
    ''' </summary>
    Public ReadOnly Property Query() As QueryExpression
        Get
            ' Setup the QueryExpression prior to returning
            SetColumns()
            SetOrders()
            SetFilter()
            SetLinkEntities()

            Return _query
        End Get
    End Property

    ''' <summary>
    ''' Used in the Query property to convert and set the ColumnBase object (of the QueryExpression object)
    ''' </summary>
    Private Sub SetColumns()
        ' if the user choosed all columns
        If _columns IsNot Nothing AndAlso _columns.AllColumns Then
            _query.ColumnSet = New AllColumns()
        ElseIf _columns IsNot Nothing AndAlso _columns.Attributes.Count > 0 Then
            ' create an ColumnSet object to assign to avoid multiple casting
            Dim builtinColumnSet As New ColumnSet()
            builtinColumnSet.Attributes = _columns.ToStringArray()

            ' re-assign the temporary ColumnSet object to the query
            _query.ColumnSet = builtinColumnSet
            ' do nothing if the user did not specify any columns
        Else
        End If
    End Sub


    ''' <summary>
    ''' Used in the Query property to convert and set the OrderExpression[] (of the QueryExpression object)
    ''' </summary>
    Private Sub SetOrders()
        ' checks to make sure that the user specified an(multiple) order(s)
        If _orders IsNot Nothing AndAlso _orders.Count > 0 Then
            _query.Orders = _orders.ToArray()
        End If
    End Sub


    ''' <summary>
    ''' Used in the Query property to convert and set the FilterExpression object (of the QueryExpression object)
    ''' </summary>
    Private Sub SetFilter()
        ' if filters & conditions have been set by the user, use them to construct the actual query
        If _criteria IsNot Nothing AndAlso (_criteria.Conditions.Count > 0 OrElse _criteria.Filters.Count > 0) Then
            _query.Criteria = BuildFilter(_criteria)
            ' do nothing since the user did not specify any filters and/or conditions
        Else
        End If
    End Sub


    ''' <summary>
    ''' Recursive function that dynamically creates a FilterExpression object from a FilterExpressionHelper object
    ''' (linking all the conditions and nested filters)
    ''' </summary>
    ''' <param name="helperFilter">A FilterExpressionHelper object that needs to be converted</param>
    ''' <returns>A FilterExpression object that can be used in the QueryExpression object</returns>
    Private Function BuildFilter(ByVal helperFilter As FilterExpressionHelper) As FilterExpression
        Dim builtinFilter As New FilterExpression()
        builtinFilter.FilterOperator = helperFilter.FilterOperator
        builtinFilter.Conditions = helperFilter.Conditions.ToConditionExpressionArray()

        ' if there are nested filters
        If helperFilter.Filters IsNot Nothing AndAlso helperFilter.Filters.Count > 0 Then
            ' recursively iterates through child filters
            Dim childFilters As FilterExpression() = New FilterExpression(helperFilter.Filters.Count - 1) {}
            Dim index As Integer = 0
            While index < childFilters.Length
                childFilters(index) = BuildFilter(helperFilter.Filters(index))
                System.Math.Max(System.Threading.Interlocked.Increment(index), index - 1)
            End While
            builtinFilter.Filters = childFilters
        End If

        Return builtinFilter
    End Function


    ''' <summary>
    ''' Used in the Query property object to convert and set the LinkEntity[] (of the QueryExpression object)
    ''' </summary>
    Private Sub SetLinkEntities()
        ' if link entities have been set by the user, use them to construct the actual query
        If _linkEntities IsNot Nothing AndAlso _linkEntities.Count > 0 Then
            _query.LinkEntities = New LinkEntity(_linkEntities.Count - 1) {}

            ' iterate through all the linked entities
            Dim index As Integer = 0
            While index < _query.LinkEntities.Length
                _query.LinkEntities(index) = BuildLinkEntity(_linkEntities(index))
                System.Math.Max(System.Threading.Interlocked.Increment(index), index - 1)
            End While
            ' do nothing since the user did not specify any linked entities
        Else
        End If
    End Sub


    ''' <summary>
    ''' Recursive function that dynamically creates a LinkEntity object from a LinkEntityHelper object
    ''' (linking all the nested linked entities as well as the filter)
    ''' </summary>
    ''' <param name="helperLinkEntity">A LinkEntityHelper object that needs to be converted</param>
    ''' <returns>A LinkEntity object that can be used in the QueryExpression object</returns>
    Private Function BuildLinkEntity(ByVal helperLinkEntity As LinkEntityHelper) As LinkEntity
        Dim builtinLinkEntity As New LinkEntity()

        ' sets the properties
        builtinLinkEntity.LinkFromEntityName = helperLinkEntity.FromEntityName
        builtinLinkEntity.LinkFromAttributeName = helperLinkEntity.FromAttributeName
        builtinLinkEntity.LinkToEntityName = helperLinkEntity.ToEntityName
        builtinLinkEntity.LinkToAttributeName = helperLinkEntity.ToAttributeName
        builtinLinkEntity.JoinOperator = helperLinkEntity.JoinOperator

        builtinLinkEntity.LinkCriteria = BuildFilter(helperLinkEntity.Criteria)

        ' if there are nested linked entities
        If helperLinkEntity.LinkEntities IsNot Nothing AndAlso helperLinkEntity.LinkEntities.Count > 0 Then
            ' recursively iterates through child linked entities
            Dim childLinkEntities As LinkEntity() = New LinkEntity(helperLinkEntity.LinkEntities.Count) {}
            Dim index As Integer = 0
            While index < childLinkEntities.Length
                childLinkEntities(index) = BuildLinkEntity(helperLinkEntity.LinkEntities(index))
                System.Math.Max(System.Threading.Interlocked.Increment(index), index - 1)
            End While
            builtinLinkEntity.LinkEntities = childLinkEntities
        End If

        Return builtinLinkEntity
    End Function

    ''' <summary>
    ''' Used to aid in the creation of a query
    ''' </summary>
    ''' <param name="name">A EntityName enum that specifies which entity</param>
    Public Sub New(ByVal name As EntityName)
        Me.New(name.ToString())
    End Sub

    ''' <summary>
    ''' Used to aid in the creation of a query
    ''' </summary>
    ''' <param name="entityName">A string that corresponds to the name of a custom or built-in entity</param>
    Public Sub New(ByVal entityName As String)
        ' instantiate the QueryExpression object
        _query = New QueryExpression()
        _query.EntityName = entityName

        ' instantiate custom objects
        _columns = New ColumnSetHelper()
        _criteria = New FilterExpressionHelper()
        _orders = New OrderExpressionCollection()
        _linkEntities = New LinkEntityHelperCollection(_query.EntityName)
    End Sub

End Class

''' <summary>
''' Used by the ColumnSetHelper class to keep track of the columns
''' </summary>
''' <remarks>Unlike the other collection classes, this class is used internally</remarks>
Public Class ColumnsCollection
    Inherits System.Collections.CollectionBase

    Friend Sub AddColumn(ByVal attributeName As String)
        ' add only if the attribute does not already exist in the list
        If Not List.Contains(attributeName) Then
            List.Add(attributeName)
        End If
    End Sub

    Friend Function ToStringArray() As String()
        ' initialize an array to the number of columns in the columns collection
        Dim returnArray As String() = New String(List.Count - 1) {}

        ' populate the array
        Dim index As Integer = 0
        While index < returnArray.Length
            returnArray(index) = DirectCast(List(index), String)
            System.Math.Max(System.Threading.Interlocked.Increment(index), index - 1)
        End While

        Return returnArray
    End Function
End Class

Public Class ColumnSetHelper
    ' Fields
    Private _attributes As ColumnsCollection
    Private _allColumns As Boolean

    ''' <summary>
    ''' A collection representing the attributes/columns the query will return
    ''' </summary>
    Public ReadOnly Property Attributes() As ColumnsCollection
        Get
            Return _attributes
        End Get
    End Property

    Friend ReadOnly Property AllColumns() As Boolean
        Get
            Return _allColumns
        End Get
    End Property

    ''' <summary>
    ''' Creates a ColumnSetHelper object that will be used to aid which columns will be returned by the query
    ''' </summary>
    Public Sub New()
        _attributes = New ColumnsCollection()
    End Sub

    ''' <summary>
    ''' Adds a column to the list of attributes that will be returned by the query
    ''' </summary>
    ''' <param name="attributeName">Specifies which attribute will be returned</param>
    Public Sub AddColumn(ByVal attributeName As String)
        ' "unchecks" all columns
        If _allColumns Then
            _allColumns = False
        End If

        _attributes.AddColumn(attributeName)
    End Sub

    ''' <summary>
    ''' Adds a set of columns to the list of attributes that will be returned by the query
    ''' </summary>
    ''' <param name="attributeNames">Specifies which attribute(s) will be returned</param>
    Public Sub AddColumns(ByVal ParamArray attributeNames As String())
        For Each attributeName As String In attributeNames
            Me.AddColumn(attributeName)
        Next
    End Sub

    ''' <summary>
    ''' Specifies the query will return all attributes for an entity record
    ''' </summary>
    Public Sub AddAllColumns()
        ' enables all columns (although the columns in this helper class are preserved)
        _allColumns = True
    End Sub

    Friend Function ToStringArray() As String()
        Return _attributes.ToStringArray()
    End Function
End Class

Public Class OrderExpressionCollection
    Inherits System.Collections.CollectionBase

    ''' <summary>
    ''' Provides access to the underlying collection of OrderExpressions
    ''' </summary>
    Default Public ReadOnly Property Item(ByVal index As Integer) As OrderExpression
        Get
            Return DirectCast(List(index), OrderExpression)
        End Get
    End Property

    ''' <summary>
    ''' Adds an order to the collection
    ''' </summary>
    ''' <param name="attributeName">The name of the attribute where an order will be applied for the query</param>
    ''' <param name="orderType">An OrderType enum that specifies what kind of ordering to apply on the attribute</param>
    Public Sub Add(ByVal attributeName As String, ByVal orderType As OrderType)
        Dim order As New OrderExpression()

        order.AttributeName = attributeName
        order.OrderType = orderType

        List.Add(order)
    End Sub

    Friend Function ToArray() As OrderExpression()
        ' initialize the string array to the number of orders in the internal list 
        Dim returnArray As OrderExpression() = New OrderExpression(List.Count - 1) {}

        ' populate the array
        Dim index As Integer = 0
        While index < returnArray.Length
            returnArray(index) = DirectCast(List(index), OrderExpression)
            System.Math.Max(System.Threading.Interlocked.Increment(index), index - 1)
        End While

        Return returnArray
    End Function
End Class

Public Class LinkEntityHelper
    Private _fromEntityName As String
    Private _fromAttributeName As String
    Private _toEntityName As String
    Private _toAttributeName As String
    Private _joinOperator As JoinOperator
    Private _criteria As FilterExpressionHelper
    Private _linkEntities As LinkEntityHelperCollection

    ''' <summary>
    ''' The entity that is being linked from in the query
    ''' </summary>
    ''' <remarks>In the simple case, this is generally the main entity</remarks>
    Public ReadOnly Property FromEntityName() As String
        Get
            Return _fromEntityName
        End Get
    End Property

    ''' <summary>
    ''' The attribute that is being linked from in the FromEntityName entity
    ''' </summary>
    Public ReadOnly Property FromAttributeName() As String
        Get
            Return _fromAttributeName
        End Get
    End Property

    ''' <summary>
    ''' The entity that is being linked to in the query
    ''' </summary>
    Public ReadOnly Property ToEntityName() As String
        Get
            Return _toEntityName
        End Get
    End Property

    ''' <summary>
    ''' The attribute that is being linked to in the ToEntityName entity (the "linked" entity)
    ''' </summary>
    Public ReadOnly Property ToAttributeName() As String
        Get
            Return _toAttributeName
        End Get
    End Property

    ''' <summary>
    ''' A builtin JoinOperator enum that specifies what kind of join will be applied to the main entity and linked entity
    ''' </summary>
    Public ReadOnly Property JoinOperator() As JoinOperator
        Get
            Return _joinOperator
        End Get
    End Property

    ''' <summary>
    ''' A filter that will be applied to the linked entity
    ''' </summary>
    Public Property Criteria() As FilterExpressionHelper
        Get
            Return _criteria
        End Get
        Set(ByVal value As FilterExpressionHelper)
            _criteria = value
        End Set
    End Property

    ''' <summary>
    ''' A set of child linked entities that links to the linked entity (ToLinkEntity)
    ''' </summary>
    Public ReadOnly Property LinkEntities() As LinkEntityHelperCollection
        Get
            Return _linkEntities
        End Get
    End Property

    ''' <summary>
    ''' Used to aid linking entities in a query
    ''' </summary>
    ''' <param name="fromEntityName">The entity that is being linked from</param>
    ''' <param name="fromAttributeName">The attribute that is being linked from in the FromEntityName entity</param>
    ''' <param name="toEntityName">The entity that is being linked to</param>
    ''' <param name="toAttributeName">The attribute that is being linked to in the ToEntityName entity</param>
    ''' <param name="joinOperator">Specifies what kind of join will happen between the FromEntityName entity and ToEntityName entity</param>
    Public Sub New(ByVal fromEntityName As String, ByVal fromAttributeName As String, ByVal toEntityName As String, ByVal toAttributeName As String, ByVal joinOperator As JoinOperator)
        _fromEntityName = fromEntityName
        _fromAttributeName = fromAttributeName
        _toEntityName = toEntityName
        _toAttributeName = toAttributeName
        _joinOperator = joinOperator

        _criteria = New FilterExpressionHelper()
        _linkEntities = New LinkEntityHelperCollection(_toEntityName)
    End Sub

End Class

Public Class LinkEntityHelperCollection
    Inherits System.Collections.CollectionBase
    ' Fields
    Private _fromEntityName As String

    ''' <summary>
    ''' The entity that is being mapped from
    ''' </summary>
    Public ReadOnly Property FromEntityName() As String
        Get
            Return _fromEntityName
        End Get
    End Property

    ''' <summary>
    ''' Provides access to the underlying collection of LinkEntityHelpers
    ''' </summary>
    Default Public ReadOnly Property Item(ByVal index As Integer) As LinkEntityHelper
        Get
            Return DirectCast(List(index), LinkEntityHelper)
        End Get
    End Property

    ''' <summary>
    ''' Used to create a collection of LinkEntityHelper objects
    ''' </summary>
    ''' <param name="fromEntityName">Specifies the entity that is being mapped from</param>
    Public Sub New(ByVal fromEntityName As String)
        _fromEntityName = fromEntityName
    End Sub

    ''' <summary>
    ''' Used to add a linked entity to the collection
    ''' </summary>
    ''' <param name="fromAttributeName">Specifies the attribute that is being mapped from in the query</param>
    ''' <param name="toEntityName">Specifies the entity that is being mapped to in the query</param>
    ''' <param name="toAttributeName">Specifies the attribute that is being mapped to in the query</param>
    ''' <returns>A LinkEntityHelper object, that can be stored and used later to add filters</returns>
    Public Function AddLink(ByVal fromAttributeName As String, ByVal toEntityName As String, ByVal toAttributeName As String) As LinkEntityHelper
        Return AddLink(fromAttributeName, toEntityName, toAttributeName, JoinOperator.Inner)
    End Function

    ''' <summary>
    ''' Used to add a linked entity to the collection
    ''' </summary>
    ''' <param name="fromAttributeName">Specifies the attribute that is being mapped from in the query</param>
    ''' <param name="toEntityName">Specifies the entity that is being mapped to in the query</param>
    ''' <param name="toAttributeName">Specifies the attribute that is being mapped to in the query</param>
    ''' <param name="joinOperator">Specifies how the entities will be joined</param>
    ''' <returns>A LinkEntityHelper object, that can be stored and used later to add filters</returns>
    Public Function AddLink(ByVal fromAttributeName As String, ByVal toEntityName As String, ByVal toAttributeName As String, ByVal joinOperator As JoinOperator) As LinkEntityHelper
        Dim linkEntity As New LinkEntityHelper(_fromEntityName, fromAttributeName, toEntityName, toAttributeName, joinOperator)
        List.Add(linkEntity)

        Return linkEntity
    End Function
End Class

Public Class FilterExpressionHelper

    ' Fields
    Private _filterOperator As LogicalOperator
    Private _conditions As ConditionExpressionHelperCollection
    Private _filters As FilterExpressionHelperCollection

    ''' <summary>
    ''' Specifies what LogicalOperator enum will be used to evaluate the conditions
    ''' </summary>
    ''' <remarks>Defaults to 'And'</remarks>
    Public Property FilterOperator() As LogicalOperator
        Get
            Return _filterOperator
        End Get
        Set(ByVal value As LogicalOperator)
            _filterOperator = value
        End Set
    End Property

    ''' <summary>
    ''' A collection of conditions that will be used by the filter in the query
    ''' </summary>
    Public ReadOnly Property Conditions() As ConditionExpressionHelperCollection
        Get
            Return _conditions
        End Get
    End Property

    ''' <summary>
    ''' A nested set of child filters
    ''' </summary>
    Public ReadOnly Property Filters() As FilterExpressionHelperCollection
        Get
            Return _filters
        End Get
    End Property

    ''' <summary>
    ''' Used to aid in the creation of a filter
    ''' </summary>
    Public Sub New()
        _filterOperator = LogicalOperator.[And]
        _conditions = New ConditionExpressionHelperCollection()
        _filters = New FilterExpressionHelperCollection()
    End Sub

End Class

Public Class ConditionExpressionHelper

    ' Fields
    Friend _conditionExpression As ConditionExpression

    ''' <summary>
    ''' Specifies which attribute will have the condition applied to
    ''' </summary>
    Public Property AttributeName() As String
        Get
            Return _conditionExpression.AttributeName
        End Get
        Set(ByVal value As String)
            _conditionExpression.AttributeName = value
        End Set
    End Property

    ''' <summary>
    ''' A ConditionOperator enum that specifies which operation will be applied to the specified attribute
    ''' </summary>
    Public Property ConditionOperator() As ConditionOperator
        Get
            Return _conditionExpression.[Operator]
        End Get
        Set(ByVal value As ConditionOperator)
            _conditionExpression.[Operator] = value
        End Set
    End Property

    ''' <summary>
    ''' Optional (depending on the specified ConditionOperator) that will specify what parameters the ConditionOperator will use
    ''' </summary>
    ''' <remarks>All values will be casted as an object</remarks>
    Public ReadOnly Property Values() As Object()
        Get
            Return _conditionExpression.Values
        End Get
    End Property

    ''' <summary>
    ''' Used to aid in creating a condition for a filter
    ''' </summary>
    Public Sub New()
        _conditionExpression = New ConditionExpression()
    End Sub

    ''' <summary>
    ''' Used to aid in creating a condition for a filter
    ''' </summary>
    ''' <param name="attributeName">Specifies which attribute the condition will be applied to</param>
    ''' <param name="conditionOperator">Specifies which condition will be applied</param>
    Public Sub New(ByVal attributeName As String, ByVal conditionOperator As ConditionOperator)
        Me.New()
        _conditionExpression.AttributeName = attributeName
        _conditionExpression.[Operator] = conditionOperator
    End Sub

    ''' <summary>
    ''' Used to aid in creating a condition for a filter
    ''' </summary>
    ''' <param name="attributeName">Specifies which attribute the condition will be applied to</param>
    ''' <param name="conditionOperator">Specifies which condition will be applied</param>
    ''' <param name="value">Specifies what parameter the condition will use to apply to the attribute specified</param>
    Public Sub New(ByVal attributeName As String, ByVal conditionOperator As ConditionOperator, ByVal value As Object)
        Me.New(attributeName, conditionOperator)
        _conditionExpression.Values = New Object() {value}
    End Sub

    ''' <summary>
    ''' Used to aid in creating a condition for a filter
    ''' </summary>
    ''' <param name="attributeName">Specifies which attribute the condition will be applied to</param>
    ''' <param name="conditionOperator">Specifies which condition will be applied</param>
    ''' <param name="values">Specifies what parameters the condition will use to apply to the attribute specified</param>
    Public Sub New(ByVal attributeName As String, ByVal conditionOperator As ConditionOperator, ByVal values As Object())
        Me.New(attributeName, conditionOperator)
        _conditionExpression.Values = values
    End Sub

End Class

Public Class ConditionExpressionHelperCollection
    Inherits System.Collections.CollectionBase

    ''' <summary>
    ''' Provides access to the underlying collection of ConditionExpressionHelpers
    ''' </summary>
    Default Public ReadOnly Property Item(ByVal index As Integer) As ConditionExpressionHelper
        Get
            Return DirectCast(List(index), ConditionExpressionHelper)
        End Get
    End Property

    ''' <summary>
    ''' Used to add a condition to the collection
    ''' </summary>
    ''' <param name="attributeName">Specifies which attribute the condition will be applied to</param>
    ''' <param name="conditionOperator">Specifies which condition will be applied</param>
    Public Sub AddCondition(ByVal attributeName As String, ByVal conditionOperator As ConditionOperator)
        Dim condition As New ConditionExpressionHelper(attributeName, conditionOperator)
        List.Add(condition)
    End Sub

    ''' <summary>
    ''' Used to add a condition to the collection
    ''' </summary>
    ''' <param name="attributeName">Specifies which attribute the condition will be applied to</param>
    ''' <param name="conditionOperator">Specifies which condition will be applied</param>
    ''' <param name="value">Specifies what parameter the condition will use to apply to the attribute specified</param>
    Public Sub AddCondition(ByVal attributeName As String, ByVal conditionOperator As ConditionOperator, ByVal value As Object)
        Dim condition As New ConditionExpressionHelper(attributeName, conditionOperator, value)
        List.Add(condition)
    End Sub

    ''' <summary>
    ''' Used to add a condition to the collection
    ''' </summary>
    ''' <param name="attributeName">Specifies which attribute the condition will be applied to</param>
    ''' <param name="conditionOperator">Specifies which condition will be applied</param>
    ''' <param name="values">Specifies what parameters the condition will use to apply to the attribute specified</param>
    Public Sub AddCondition(ByVal attributeName As String, ByVal conditionOperator As ConditionOperator, ByVal values As Object())
        Dim condition As New ConditionExpressionHelper(attributeName, conditionOperator, values)
        List.Add(condition)
    End Sub

    ''' <summary>
    ''' Used to add a condition to the collection
    ''' </summary>
    ''' <param name="condition">A ConditionExpressionHelper object that will be added to the collection</param>
    Public Sub AddCondition(ByVal condition As ConditionExpressionHelper)
        List.Add(condition)
    End Sub

    Friend Function ToConditionExpressionArray() As ConditionExpression()
        ' initialize the condition expression array
        Dim returnArray As ConditionExpression() = New ConditionExpression(List.Count - 1) {}

        ' populate the array
        Dim index As Integer = 0
        While index < returnArray.Length
            returnArray(index) = DirectCast((DirectCast(List(index), ConditionExpressionHelper))._conditionExpression, ConditionExpression)
            System.Math.Max(System.Threading.Interlocked.Increment(index), index - 1)
        End While

        Return returnArray
    End Function

End Class

Public Class FilterExpressionHelperCollection
    Inherits System.Collections.CollectionBase

    ''' <summary>
    ''' Provides access to the underlying collection of FilterExpressionHelpers
    ''' </summary>
    Default Public ReadOnly Property Item(ByVal index As Integer) As FilterExpressionHelper
        Get
            Return DirectCast(List(index), FilterExpressionHelper)
        End Get
    End Property

    ''' <summary>
    ''' Used to add a child filter to the current/parent filter
    ''' </summary>
    ''' <param name="childFilter">A FilterExpressionHelper object that will be added as a child filter to the main filter</param>
    Public Sub AddFilter(ByVal childFilter As FilterExpressionHelper)
        List.Add(childFilter)
    End Sub
End Class

